package com.game.shudu

import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity

/**
 * 正文页面
 */
class Game : AppCompatActivity() {
    companion object {
        val KEY_DIFFICULTY = "org.example.sudoku.difficulty"
        val DIFFICULTY_EASY = 0
        val DIFFICULTY_MEDIUM = 1
        val DIFFICULTY_HARD = 2

        val PREF_PUZZLE = "puzzle"
        val DIFFICULTY_CONTINUE = -1
    }

    private var pieces = Array(9) { Array(9) { PieceBean(0, 1) } }//棋谱数组二

    //三维数组（指定坐标点的周边数字0-9不重复集合）
    private val used: Array<Array<IntArray>> = Array(9) { Array(9) { IntArray(9) } }
    lateinit var puzzleView: PuzzleView


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val diff = intent.getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY)
        getPieces(diff)
        calculateUsedTiles()

        puzzleView = PuzzleView(this)
        setContentView(puzzleView)
        supportActionBar?.hide()  //隐藏ActionBar
        puzzleView.requestFocus()
    }

    override fun onResume() {
        super.onResume()
        if (Prefs.getMusic(this)) Music.play(this, R.raw.fresh_power)
    }

    override fun onPause() {
        super.onPause()
        if (Prefs.getMusic(this)) Music.stop(this)

        getPreferences(Context.MODE_PRIVATE).edit().putString(PREF_PUZZLE, dataToJson(pieces))
            .apply()
    }

    /**
     * 随机生成简易模式的棋谱
     */
    private fun getPieces(diff: Int) {
        when (diff) {
            DIFFICULTY_CONTINUE -> { //继续游戏
                val piecesString = getPreferences(Context.MODE_PRIVATE).getString(PREF_PUZZLE, "")
                if (piecesString!!.contains(",") && piecesString.contains("-")) {
                    val strings = piecesString.split(",")
                    var count = 0
                    for (i in 0..8) {
                        for (j in 0..8) {
                            pieces[i][j] = PieceBean(
                                Integer.parseInt(strings[count].split("-")[0]),
                                Integer.parseInt(strings[count].split("-")[1])
                            )
                            Log.v("Game->读取2：", pieces[i][j].toString())
                            count++
                        }
                    }
                }
            }
            DIFFICULTY_EASY -> initPieces(2)
            DIFFICULTY_MEDIUM -> initPieces(5)
            DIFFICULTY_HARD -> initPieces(8)
            else -> initPieces(2)
        }
    }

    /**
     * 初始化棋谱
     * level:级别
     */
    private fun initPieces(level: Int) {
        val grids = SudokuPuzzleGenerator().generatePuzzleMatrix()
        for (i in 0..8) {
            for (j in 0..8) {
                val num = if ((0..8).random() < level) 0 else grids[i][j]
                pieces[i][j] = PieceBean(num, if (num == 0) 1 else 0)
            }
        }

//        for (i in 0..8) {
//            for (j in 0..8) {
//                val calculateUsedTiles = calculateUsedTiles(i, j)//单位内存在的不重复1-9数字数组
//                val randoms = when {
//                    (0..8).random() < level -> {
//                        0
//                    }
//                    calculateUsedTiles.isNotEmpty() -> {
//                        val filter = (0..9).filter { it !in calculateUsedTiles }
//                        filter.random()//不冲突的随机数
//                    }
//                    else -> {
//                        (0..9).random()//不冲突的随机数
//                    }
//                }
//                pieces[i][j] = PieceBean(randoms, 1)
//            }
//        }
    }

    fun getPieceNum(x: Int, y: Int): Int {
        return pieces[x][y].num
    }

    fun getPieceString(x: Int, y: Int): String {
        val tile = getPieceNum(x, y)
        return if (tile == 0) "" else tile.toString()
    }

    fun getPieceBean(x: Int, y: Int): PieceBean {
        return pieces[x][y]
    }

    /**
     * 获得所有该数字的坐标
     */
    fun getNumToXy(num: Int): HashMap<Int, Int> {
        val result = HashMap<Int, Int>()
        for (i in 0..8) {
            for (j in 0..8) {
                if (pieces[i][j].num == num) {
                    result[i] = j
                }
            }
        }
        return result
    }

    /**
     * 读取指定坐标下填入的数字
     */
    private fun getUsedTiles(x: Int, y: Int): IntArray {
        return used[x][y]
    }

    /**
     * 判断填入的数字是否冲突
     */
    fun setTileIfValid(selX: Int, selY: Int, tile: Int): Boolean {
        var pieceBean = getPieceBean(selX, selY)//当前填入的数字
        val tiles = getUsedTiles(selX, selY)
        if (pieceBean.type == 0 || tiles.contains(tile)) return false
        setTile(selX, selY, tile)
        calculateUsedTiles()
        return true
    }

    private fun setTile(x: Int, y: Int, tile: Int) {
        pieces[x][y] = PieceBean(tile, 1)
    }

    private fun calculateUsedTiles() {
        for (x in 0..8) {
            for (y in 0..8) {
                used[x][y] = calculateUsedTiles(x, y)
            }
        }
    }

    private fun dataToJson(pieces: Array<Array<PieceBean>>): String {
        val result = java.lang.StringBuilder()
        for (i in 0..8) {
            for (j in 0..8) {
                result.append(",").append(pieces[i][j].num).append("-").append(pieces[i][j].type)
            }
        }
        return result.toString().replaceFirst(",", "")
    }

    /**
     * 判断填入数字是否和已有数字相冲突
     * 指定坐标点为中心的十字与9宫中0-9填过的值
     * 获得指定坐标周边填过的数字数组
     */
    private fun calculateUsedTiles(x: Int, y: Int): IntArray {
        val c = IntArray(9)//{1,0,3,0,5,0,0,0,0}
        // horizontal
        for (i in 0..8) {
            if (i == x) continue
            val t = getPieceNum(i, y)
            if (t != 0) c[t - 1] = t
        }
        // vertical
        for (i in 0..8) {
            if (i == y) continue
            val t = getPieceNum(x, i)
            if (t != 0) c[t - 1] = t
        }
        // same cell block
        val startX = x / 3 * 3
        val startY = y / 3 * 3
        for (i in startX until startX + 3) {
            for (j in startY until startY + 3) {
                if (i == x && j == y) continue
                val t = getPieceNum(i, j)
                if (t != 0) c[t - 1] = t
            }
        }
        // compress
        var nused = 0
        for (t in c) {
            if (t != 0) nused++
        }
        val c1 = IntArray(nused)//{1,3,5}
        nused = 0
        for (t in c) {
            if (t != 0) c1[nused++] = t
        }
        return c1
    }
}